﻿#include "TcpClient_T_Private.h"

#include <QBuffer>
#include <QtConcurrent/QtConcurrent>

using namespace ZTcp;

TcpClient_T_Private::TcpClient_T_Private(qintptr socketDescriptor, bool useTaskPool, QWaitCondition *waitDataTrans, QObject *parent)
    : QObject(parent),
      isConnected_(false),
      socketDescriptor_(socketDescriptor),
      socket_(nullptr),
      f_(),
      sendBuffer_(),
      localAddress_(),
      localPort_(),
      serverAddress_(),
      serverPort_(),
      taskPool_(nullptr),
      useTaskPool_(useTaskPool),
      isBusy_(false),
      waitDataTrans_(waitDataTrans) {
  /* 初始化任务池 */
  if (useTaskPool_) {
    // 默认使用cpu能支持的线程数
    taskPool_ = new QThreadPool{this};
  } else {
    // 只用1个线程
    taskPool_ = new QThreadPool{this};
    taskPool_->setMaxThreadCount(1);
  }
}

TcpClient_T_Private::~TcpClient_T_Private() {
}

void TcpClient_T_Private::bind(const QHostAddress &address, quint16 port) {
  // 记录,在多线程中再初始化socket
  localAddress_ = address;
  localPort_ = port;
}

void TcpClient_T_Private::connectToHost(const QHostAddress &address, quint16 port) {
  // 记录,在多线程中再初始化socket
  serverAddress_ = address;
  serverPort_ = port;
}

void TcpClient_T_Private::readCall(std::function<void(const QByteArray &)> f) {
  f_ = f;
}

bool TcpClient_T_Private::isConnected() {
  return isConnected_;
}

const QHostAddress &TcpClient_T_Private::localAddress() const {
  return localAddress_;
}

quint16 TcpClient_T_Private::localPort() const {
  return localPort_;
}

QHostAddress TcpClient_T_Private::peerAddress() const {
  return socket_->peerAddress();
}

quint16 TcpClient_T_Private::peerPort() const {
  return socket_->peerPort();
}

bool TcpClient_T_Private::isBusy() {
  return isBusy_;
}

void TcpClient_T_Private::setIsBusy(bool arg) {
  isBusy_.store(arg);
}

void TcpClient_T_Private::slotStart() {
  /* 初始化socket */
  socket_ = new QTcpSocket{};
  // 连接变更状态
  connect(socket_, &QTcpSocket::connected, [=] {
    isConnected_ = true;
  });
  connect(socket_, &QTcpSocket::disconnected, [=] {
    isConnected_ = false;
    emit sigDisconnected();
  });

  // 自定义的client
  if (socketDescriptor_ == -1) {
    // 设置了地址时绑定自身地址
    if (!localAddress_.toString().isEmpty()) {
      auto isOk{socket_->bind(localAddress_, localPort_)};
      if (!isOk) {
        qWarning() << "socket can't bind ip:port" << localAddress_.toString() << localPort_;
        return;
      }
    }
    // 连接
    socket_->connectToHost(serverAddress_, serverPort_);
    // 尝试等待
    socket_->waitForConnected(1000);
  } else if (!socket_->setSocketDescriptor(socketDescriptor_)) {
    // server生成的client,重置socket的底层handle
    qWarning() << __FUNCTIONW__ << __LINE__ << " set setSocketDescriptor error!";
    // 设置失败直接返回
    return;
  } else {
    // server连接的直接置为已连接状态
    isConnected_ = true;
  }

  // 连接数据接收
  connect(socket_, &QTcpSocket::readyRead, this, &TcpClient_T_Private::slotReadMsg);

  // 发送启动完成
  emit sigStartDone();
}

void TcpClient_T_Private::slotWrite(const QByteArray &arg) {
  // 没有连上直接返回
  if (!isConnected_) {
    qWarning() << "tcp is not connected";
    return;
  }

  // 繁忙
  isBusy_.store(true);

  socket_->write(arg);
  socket_->waitForBytesWritten();

  // 非繁忙
  isBusy_ = false;

  // 如果设置了等待
  if(waitDataTrans_){
    // 通知完毕
    waitDataTrans_->wakeOne();
  }
}

void TcpClient_T_Private::slotWritePtr(char *ptr, int size) {
  // 没有连上直接返回
  if (!isConnected_) {
    qWarning() << "tcp is not connected";
    return;
  }

  // 繁忙
  isBusy_.store(true);

  socket_->write(ptr, size);
  socket_->waitForBytesWritten();

  // 非繁忙
  isBusy_ = false;

  // 如果设置了等待
  if(waitDataTrans_){
    // 通知完毕
    waitDataTrans_->wakeOne();
  }
}

void TcpClient_T_Private::slotReadMsg() {
  // 读取数据
  auto data{socket_->readAll()};
  // 如果记录了有效的处理函数
  if (f_) {
    // 并发处理数据
    QtConcurrent::run(taskPool_, [=] {
      f_(data);
    });
  }
}
